package com.bnz.cart.service.impl;

import com.alibaba.fastjson.JSON;
import com.bnz.cart.dao.ItemMapper;
import com.bnz.cart.entity.Item;
import com.bnz.cart.entity.OrderItem;
import com.bnz.cart.entity.group.Cart;
import com.bnz.cart.service.CartService;
import com.bnz.common.utils.IdWorker;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class CartServiceImpl implements CartService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ItemMapper itemMapper;
    @Autowired
    private IdWorker idWorker;
    // 1. 添加商品到购物车
    @Override
    public void add(String itemId, int num, String name) {
       /* // 1.1 先从redis中取得购物车集合
        String cartStr = redisTemplate.opsForValue().get("name");
        // 1.2 先判断购物车集合是否为空，如果为空，就给它加一个[]，相当于new ArrayList()
        if (StringUtils.isBlank(cartStr)){
            cartStr = "[]";
        }
        // 1.3 将购物车集合的字符串形式转换为对象形式，得到购物车集合
        List<Cart> cartList = JSON.parseArray(cartStr, Cart.class);
        // 1.4 根据itemId得到item对象
        Item item = itemMapper.selectById(itemId);
        // 1.5 根据item对象得到sellerId
        String sellerId = item.getSellerId();
        // 1.6 根据sellerId来判断购物车集合中是否已经存在该购物车
        Cart cart = findCartBySellerId(cartList,sellerId);
        // 1.6.1 如果存在就直接修改商品数量和小计
        if (cart != null){
            // 1.6.1.1首先判断该购物车下的购物项列表是否有此商品，如果有就修改数量和小计
            OrderItem orderItem = findOrderItem(cart.getOrderItemList(),itemId);
            // 1.6.1.2如果存在就修改商品的数量和小计
            if (orderItem != null){
                // ①修改购物项中的商品数量
                orderItem.setNum(orderItem.getNum() + num);
                // ②修改购物项中的小计
                orderItem.setTotalFee(new BigDecimal(orderItem.getNum() * orderItem.getPrice().doubleValue()));
            }
            // 1.6.1.3如果不存在就创建一个新的购物项并添加到购物车中
            else {
                // ①创建一个新的购物项
                orderItem = createOrderItem(item,num);
                // ②将购物项添加到购物项集合中
                cart.getOrderItemList().add(orderItem);
            }

            // 1.6.2 一些特殊情况
            // 1.6.2.1 如果购物车中的某件购物项数量为0，那么就从购物项列表中删除该购物项
            if (orderItem.getNum() == 0){
                cart.getOrderItemList().remove(orderItem);
            }
            // 1.6.2.2 如果购物车中已经没有购物项列表了，那么就删除该购物车
            if (cart.getOrderItemList().size() == 0){
                cartList.remove(cart);
            }
        }
        // 1.6.2 如果不存在就创建一个新的购物车，并将购物车放到购物车集合中
        else {
            cart = addCart(item,num);
            cartList.add(cart);
        }
        // 1.7 将购物车集合添加到redis中
        redisTemplate.opsForValue().set(name,JSON.toJSONString(cartList),30, TimeUnit.DAYS);

    }

    // 2. 根据sellerId来判断是否存在该购物车，存在就返回该购物车
    private Cart findCartBySellerId(List<Cart> cartList, String sellerId) {
        // 2.1 遍历购物车集合
        for (Cart cart : cartList) {
            // 2.2 如果sellerId相同就代表存在购物车
            if (sellerId.equals(cart.getSellerId())){
                // 2.3 存在就返回这个购物车
                return cart;
            }
        }
        // 2.4 不然就返回空
        return null;
    }
    // 3. 购物车不存在，那么就创建一个新的购物车
    private Cart addCart(Item item, int num) {
        // 3.1 创建一个新的购物车
        Cart cart = new Cart();
        // 3.2 给购物车添加属性
        cart.setSellerId(item.getSellerId());
        cart.setSellerName(item.getSeller());
        // 3.3 没有购物项集合就创建一个新的购物项
        OrderItem orderItem = createOrderItem(item,num);
        // 3.4 创建一个新的购物项集合
        List<OrderItem> orderItemList = new ArrayList<>();
        // 3.5 将购物项添加到购物项集合中
        orderItemList.add(orderItem);
        // 3.6 为购物车设置购物项集合属性
        cart.setOrderItemList(orderItemList);
        // 3.7 返回购物车
        return cart;
    }

    // 4. 创建一个新的购物项
    private OrderItem createOrderItem(Item item, int num) {
        // 4.1 创建订单对象
        OrderItem orderItem = new OrderItem();
        // 4.2 为订单对象添加属性
        orderItem.setGoodsId(item.getGoodsId());
        orderItem.setId(idWorker.nextId());
        orderItem.setItemId(new Long(item.getId()));
        orderItem.setNum(num);
        orderItem.setPicPath(item.getImage());
        orderItem.setPrice(item.getPrice());
        orderItem.setSellerId(item.getSellerId());
        orderItem.setTitle(item.getTitle());
        orderItem.setTotalFee(new BigDecimal(num * item.getPrice().doubleValue()));
        // 4.3 返回订单对象
        return orderItem;
    }

    // 5. 根据itemId来判断是否存在购物项
    private OrderItem findOrderItem(List<OrderItem> orderItemList, String itemId) {
        // 5.1 遍历购物项集合
        for (OrderItem orderItem : orderItemList) {
            // 5.2 根据itemId判断是否存在购物项，itemId是一个String类型，orderItem.getItemId是一个lang型，如果不转换可能会出现问题
            if (itemId.equals(orderItem.getItemId() + "")){
                // 5.3 存在就返回购物项
                return orderItem;
            }
        }
        // 5.4 不存在就返回空
        return null;
    }
*/
        //1.1 从redis中取得购物车集合
        String cartStr = redisTemplate.opsForValue().get(name);
        if(StringUtils.isBlank(cartStr)){
            cartStr = "[]";
        }
        //1.2 将购物车集合的字符串转换为集合对象
        List<Cart> cartList = JSON.parseArray(cartStr,Cart.class);
        //1.3 根据itemId查询出TbItem对象
        Item item = itemMapper.selectById(itemId);
        String sellerId = item.getSellerId();
        //1.4 根据sellerId在购物车集合中查询是否存在购物车
        Cart cart = findCartBySellerId(cartList,sellerId);
        //1.5 判断是否有此购物车，
        //1.5.1 如果有此购物车就修改数量及小计金额
        if(cart != null){
            //细节：判断在此购物车的购物项列表是否有此商品
            // ① 有此商品就修改的数量及金额
            OrderItem orderItem = findOrderItem(cart.getOrderItemList(),itemId);
            if(orderItem != null){
                orderItem.setNum(orderItem.getNum() + num);
                orderItem.setTotalFee(new BigDecimal(orderItem.getPrice().doubleValue() * orderItem.getNum()));
            }else{  // ② 没有此商品就构造一个商品项并添加到这个购物车的商品项列表集合中
                orderItem = createOrderItem(item,num);          // 创建购物项
                cart.getOrderItemList().add(orderItem);         // 将购物项添加到订单列表中
            }

            //1.6 一些特殊情况的处理
            //1.6.1 如果某件商品的数量为0，就从购物车的购物项列表中将其删除
            if(orderItem.getNum() == 0){
                cart.getOrderItemList().remove(orderItem);
            }
            //1.6.2 如果购物车的购物项没有商品了，就从购物车集合中删除此购物车
            if(cart.getOrderItemList().size() == 0){
                cartList.remove(cart);
            }

        }else{ //1.5.2 如果没有此购物车，就构造一个新的购物车并放到购物车集合中
            cart = createCart(item,num);
            cartList.add(cart);
        }

        //1.7 将购物车集合添加到redis中
        redisTemplate.opsForValue().set(name,JSON.toJSONString(cartList),20, TimeUnit.DAYS);

    }

    //2. 根据sellerId在购物车列表中查询是否存在指定购物车
    private Cart findCartBySellerId(List<Cart> cartList, String sellerId) {
        for (Cart cart : cartList) {
            if (sellerId.equals(cart.getSellerId())) {
                return cart;
            }
        }
        return null;
    }
    //3. 创建一个购物车
    private Cart createCart(Item item, int num) {
        //3.1 构造一个购物车对象
        Cart cart = new Cart();
        //3.2 设置购物车属性
        cart.setSellerId(item.getSellerId());
        cart.setSellerName(item.getSeller());
        OrderItem orderItem = createOrderItem(item,num);
        List<OrderItem> orderItemList = new ArrayList<>();
        orderItemList.add(orderItem);
        cart.setOrderItemList(orderItemList);
        //3.3 返回购物车
        return cart;
    }

    //4. 创建订单对象
    private OrderItem createOrderItem(Item item, int num) {
        OrderItem orderItem = new OrderItem();
        orderItem.setId(idWorker.nextId());
        orderItem.setNum(num);
        orderItem.setTotalFee(new BigDecimal(num * item.getPrice().doubleValue()));
        orderItem.setGoodsId(item.getGoodsId());
        orderItem.setPrice(item.getPrice());
        orderItem.setPicPath(item.getImage());
        orderItem.setSellerId(item.getSellerId());
        orderItem.setItemId(new Long(item.getId()));
        orderItem.setTitle(item.getTitle());
        return orderItem;
    }
    //5. 在购物车的订单项列表中，查询是否存在指定的购物项
    private OrderItem findOrderItem(List<OrderItem> orderItemList, String itemId) {
        for (OrderItem orderItem : orderItemList) {
            if (itemId.equals(orderItem.getItemId() + "")) {
                return orderItem;
            }
        }
        return null;
    }

    // 6. 从redis中拿到购物车
    @Override
    public List<Cart> getCartList(String name) {
        // 6.1 首先要判断用户有没有登录
        if (StringUtils.isNotBlank(name)){
            // 6.2 用户登录了就从redis中拿到购物车的字符串形式
            String s = redisTemplate.opsForValue().get(name);
            // 6.3 将购物车字符串形式转换为对象的形式
            List<Cart> cartList = JSON.parseArray(s, Cart.class);
            // 6.4 得到购物车
            return cartList;
        }
        return new ArrayList<>();
    }
}
